home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
forms
/
FORMS
/
forms.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
18KB
|
643 lines
/*
* forms.c
*
* This file is part of the basis of the Forms Library.
*
* It contains the routines for building up forms and for handling the
* interaction with the user.
*
* Written by Mark Overmars
*
* Version 2.2 c
* Date Jun 21, 1993
*/
#include <stdio.h>
#include <sys/time.h>
#include "gl/gl.h"
#include "gl/device.h"
#include "forms.h"
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif
extern int sginap (long);
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif
FL_FORM *fl_current_form = NULL;
static FL_OBJECT *fl_current_group = NULL;
FL_FORM *fl_bgn_form(int type,float w,float h)
/* Starts a form definition */
{
fl_init();
if (fl_current_form != NULL)
{ fl_error("fl_bgn_form","You forgot calling fl_end_form."); }
fl_current_form = fl_make_form(w,h);
fl_add_box(type,0.0,0.0,w,h,"");
return fl_current_form;
}
void fl_end_form()
/* Ends a form definition */
{
if (fl_current_form == NULL)
{ fl_error("fl_end_form","Ending form definition of NULL form."); return; }
fl_current_form = NULL;
}
void fl_addto_form(FL_FORM *form)
/* Reopens a form for input */
{
if (fl_current_form != NULL)
{ fl_error("fl_addto_form","You forgot calling fl_end_form"); }
if (form == NULL)
{ fl_error("fl_addto_form","Adding to NULL form."); return; }
fl_current_form = form;
}
FL_OBJECT *fl_bgn_group()
/* Starts a group definition */
{
if (fl_current_form == NULL)
{ fl_error("fl_bgn_group","Starting group in NULL form."); return NULL;}
if (fl_current_group != NULL)
{ fl_error("fl_bgn_group","You forgot calling fl_end_group."); fl_end_group();}
fl_current_group = fl_make_object(FL_BEGIN_GROUP,0,0.0,0.0,0.0,0.0,"",NULL);
fl_add_object(fl_current_form,fl_current_group);
return fl_current_group;
}
FL_OBJECT *fl_end_group()
/* Ends a group definition */
{
FL_OBJECT *ob;
if (fl_current_form == NULL)
{ fl_error("fl_end_group","Ending group in NULL form."); return NULL; }
if (fl_current_group == NULL)
{ fl_error("fl_end_group","Ending NULL group."); return NULL; }
fl_current_group = NULL;
ob = fl_make_object(FL_END_GROUP,0,0.0,0.0,0.0,0.0,"",NULL);
fl_add_object(fl_current_form,ob);
return ob;
}
/************************ Doing the Interaction *************************/
#define MAX_FORM 40
static FL_FORM *forms[MAX_FORM]; /* The forms being shown. */
static int formnumb = 0; /* Their number. */
static FL_FORM *mouseform = NULL; /* The current form under mouse*/
static FL_OBJECT *pushobj = NULL; /* latest pushed object */
static FL_OBJECT *mouseobj = NULL; /* object under the mouse */
static void reshape_form(FL_FORM *form)
/* Corrects the shape of the form based on the shape of its window */
{
long w, h;
fl_save_user_window();
fl_set_forms_window(form);
getsize(&w,&h);
getorigin(&(form->x),&(form->y));
if ( w != (long) form->w || h != (long) form->h)
fl_set_form_size(form, w, h);
ortho2(-0.5, (int) form->w - 0.5, -0.5, (int) form->h - 0.5);
fl_restore_user_window();
}
static void reshape_window(FL_FORM *form)
/* Corrects the shape of the window based on the shape of the form */
{
if (form->visible <= 0) return;
fl_save_user_window();
fl_set_forms_window(form);
winposition((long) form->x, (long) (form->x+form->w -1),
(long) form->y, (long) (form->y+form->h -1));
fl_restore_user_window();
}
void fl_scale_form(FL_FORM *form, float xsc, float ysc)
/* Scales a form with the given scaling factors. */
{
FL_OBJECT *obj;
if (form == NULL)
{ fl_error("fl_scale_form","Scaling NULL form."); return;}
obj = form->first;
while (obj != NULL)
{
obj->x = obj->x * xsc;
obj->y = obj->y * ysc;
obj->w = obj->w * xsc;
obj->h = obj->h * ysc;
obj = obj->next;
}
form->w = form->w * xsc;
form->h = form->h * ysc;
reshape_window(form);
}
void fl_set_form_size(FL_FORM *form, long w, long h)
/* Sets the size of the form on the screen. */
{
if (form == NULL)
{ fl_error("fl_set_form_size","Changing size of NULL form."); return;}
fl_scale_form(form, ((float) w) / form->w, ((float) h) / form->h);
}
void fl_set_form_position(FL_FORM *form, long x, long y)
/* Sets the position of the form on the screen. */
{
if (form == NULL)
{ fl_error("fl_set_form_position","Changing position NULL form."); return;}
form->x = x; form->y = y;
reshape_window(form);
}
void fl_set_form_hotspot(FL_FORM *form, float x, float y)
/* Sets the position of the form on the screen. */
{
if (form == NULL)
{ fl_error("fl_set_form_hotspot","setting hotspot for NULL form.");
return;}
form->hotx = x; form->hoty = y;
}
long fl_show_form(FL_FORM *form,int place,int border,const char *name)
/* Displays a particular form. Returns window handle. */
{
long screenw,screenh;
if (formnumb == MAX_FORM)
{ fl_error("fl_show_form","Can show only 40 forms."); return -1; }
if (form == NULL)
{ fl_error("fl_show_form","Trying to display NULL form."); return -1;}
if (form->visible ) return form->window;
fl_save_user_window();
forms[formnumb++] = form;
form->deactivated = 0;
screenw = getgdesc(GD_XPMAX); screenh = getgdesc(GD_YPMAX);
if (place == FL_PLACE_SIZE)
prefsize( (int) form->w, (int) form->h);
else if (place == FL_PLACE_ASPECT)
keepaspect( (int) form->w, (int) form->h);
else if (place != FL_PLACE_FREE)
{
switch(place)
{
case FL_PLACE_CENTER:
form->x = (int) ((screenw - form->w)/2.);
form->y = (int) ((screenh - form->h)/2.);
break;
case FL_PLACE_MOUSE:
form->x = (int) (getvaluator(MOUSEX) - 0.5*form->w);
form->y = (int) (getvaluator(MOUSEY) - 0.5*form->h);
break;
case FL_PLACE_FULLSCREEN:
form->x = 0;
form->y = 0;
fl_set_form_size(form, screenw, screenh);
break;
case FL_PLACE_HOTSPOT: /*TCZ */
if(form->hotx < 0.0) {/* never set */
form->x = (int) (getvaluator(MOUSEX) - 0.5*form->w);
form->y = (int) (getvaluator(MOUSEY) - 0.5*form->h);
}
else {
long it = border ? 12:1;
if((form->x = (getvaluator(MOUSEX) - form->hotx)) < it) {
form->x = it;
setvaluator(MOUSEX, form->x + form->hotx, 0, getgdesc(GD_XPMAX));
}
if(form->x > (long)(screenw - form->w -it)) {
form->x = (long) (screenw - form->w - it);
setvaluator(MOUSEX, form->x + form->hotx, 0, getgdesc(GD_XPMAX));
}
if((form->y = (getvaluator(MOUSEY) - form->hoty)) < it) {
form->y = it;
setvaluator(MOUSEY, form->y + form->hoty, 0, getgdesc(GD_YPMAX));
}
if(form->y > (long)(screenh - form->h -it)) {
form->y = (long) (screenh - form->h - it);
setvaluator(MOUSEY, form->y + form->hoty, 0, getgdesc(GD_YPMAX));
}
}
break;
}
if(place == FL_PLACE_POSITION){
/* Correct form position */
if (form->x < 0) form->x = screenw - form->w + form->x -1.0;
if (form->y < 0) form->y = screenh - form->h + form->y -1.0;
}
if (form->x < 0) form->x = 0.0;
if (form->x > screenw - form->w) form->x = screenw - form->w;
if (form->y < 0) form->y = 0.0;
if (form->y > screenh - form->h) form->y = screenh - form->h;
prefposition((long) form->x, (long) (form->x+form->w -1),
(long) form->y, (long) (form->y+form->h -1));
}
if (! border) noborder();
if (name == NULL)
form->window = winopen("Form");
else
form->window = winopen((char *)name);
form->visible = 1;
if (form->doublebuf) doublebuffer();
if (fl_rgbmode) RGBmode();
gconfig();
ortho2(-0.5, (int) form->w - 0.5, -0.5, (int) form->h - 0.5);
/* Clear window */
fl_color(FL_COL1);
clear();
if (form->doublebuf) swapbuffers();
/* Queue the devices */
qdevice(MOUSE3); qdevice(MOUSE2); qdevice(MOUSE1);
qdevice(KEYBD);
qdevice(LEFTARROWKEY); qdevice(RIGHTARROWKEY);
qdevice(UPARROWKEY); qdevice(DOWNARROWKEY);
qdevice(WINQUIT);
qdevice(WINFREEZE);
qdevice(WINTHAW);
reshape_form(form);
fl_redraw_form(form);
fl_restore_user_window();
return form->window;
}
void fl_hide_form(FL_FORM *form)
/* Hides a particular form */
{
int i;
FL_OBJECT *obj;
if (form == NULL)
{ fl_error("fl_hide_form","Hiding NULL form."); return; }
if (form->window < 0 )
{ fl_error("fl_hide_form","Hiding invisible form."); return; }
fl_save_user_window();
fl_set_forms_window(form);
for (i=0; i<formnumb; i++)
if (form == forms[i]) forms[i] = forms[--formnumb];
if (mouseobj != NULL && mouseobj->form == form)
{
obj = mouseobj; mouseobj = NULL;
fl_handle_object(obj,FL_LEAVE,0.0,0.0,0);
}
if (pushobj != NULL && pushobj->form == form)
{
obj = pushobj; pushobj = NULL;
fl_handle_object(obj,FL_RELEASE,0.0,0.0,0);
}
if (form->focusobj != NULL)
{
obj = form->focusobj;
fl_handle_object(form->focusobj,FL_UNFOCUS,0.0,0.0,0);
fl_handle_object(obj,FL_FOCUS,0.0,0.0,0);
}
winclose(form->window);
form->window = -1;
form->deactivated = 1;
form->visible = 0;
fl_restore_user_window();
}
void fl_activate_form(FL_FORM *form)
/* activates a form */
{
if (form == NULL)
{ fl_error("fl_activate_form","Activating NULL form."); return; }
if (form->deactivated) form->deactivated--;
}
void fl_deactivate_form(FL_FORM *form)
/* deactivates a form */
{
if (form == NULL)
{ fl_error("fl_deactivate_form","Deactivating NULL form."); return; }
if (!form->deactivated && mouseobj != NULL && mouseobj->form == form)
fl_handle_object(mouseobj,FL_LEAVE,0.0,0.0,0);
form->deactivated++;
}
void fl_activate_all_forms()
/* activates all forms */
{
int i;
for (i=0; i<formnumb; i++) fl_activate_form(forms[i]);
}
void fl_deactivate_all_forms()
/* deactivates all forms */
{
int i;
for (i=0; i<formnumb; i++) fl_deactivate_form(forms[i]);
}
static void fl_handle_form(FL_FORM *form, int event, int key)
/* updates a form according to an event */
{
int i;
FL_OBJECT *obj, *obj1;
float xx,yy;
if (form == NULL || ! form->visible) return;
if (form->deactivated && event != FL_DRAW) return;
if (event != FL_STEP) fl_set_forms_window(form); /* Avoid unnecessary winsets */
if (event != FL_STEP && event != FL_DRAW)
{
fl_get_mouse(&xx,&yy);
obj = fl_find_last(form,FL_FIND_MOUSE,xx,yy);
}
switch (event)
{
case FL_DRAW: /* form must be redrawn */
reshapeviewport();
reshape_form(form);
fl_redraw_form(form);
break;
case FL_ENTER: /* Mouse did enter the form */
mouseobj = obj;
fl_handle_object(mouseobj,FL_ENTER,xx,yy,0);
break;
case FL_LEAVE: /* Mouse did leave the form */
fl_handle_object(mouseobj,FL_LEAVE,xx,yy,0);
mouseobj = NULL;
break;
case FL_MOUSE: /* Mouse position changed in the form */
if (pushobj != NULL)
fl_handle_object(pushobj,FL_MOUSE,xx,yy,0);
else if (obj != mouseobj)
{
fl_handle_object(mouseobj,FL_LEAVE,xx,yy,0);
fl_handle_object(mouseobj = obj,FL_ENTER,xx,yy,0);
}
else if (mouseobj != NULL)
fl_handle_object(mouseobj,FL_MOVE,xx,yy,0);
break;
case FL_PUSH: /* Mouse was pushed inside the form */
/* change input focus */
if ( obj != NULL && obj->input && form->focusobj != obj)
{
fl_handle_object(form->focusobj,FL_UNFOCUS,xx,yy,0);
fl_handle_object(obj,FL_FOCUS,xx,yy,0);
}
/* handle a radio button */
if (obj != NULL && obj->radio)
{
obj1 = obj;
while (obj1->prev != NULL && obj1->objclass != FL_BEGIN_GROUP)
obj1 = obj1->prev;
while (obj1 != NULL && obj1->objclass != FL_END_GROUP)
{
if ( obj1->radio && obj1->pushed )
{
fl_handle_object_direct(obj1,FL_PUSH,xx,yy,0);
fl_handle_object_direct(obj1,FL_RELEASE,xx,yy,0);
obj1->pushed = 0;
}
obj1 = obj1->next;
}
}
/* push the object */
fl_handle_object(obj,FL_PUSH,xx,yy,key);
pushobj = obj;
break;
case FL_RELEASE: /* Mouse was released inside the form */
obj = pushobj; pushobj = NULL;
fl_handle_object(obj,FL_RELEASE,xx,yy,key);
break;
case FL_KEYBOARD: /* A key was pressed */
/* Check whether the <Alt> key is pressed */
if (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY)) key +=128;
/* Check whether an object has this as shortcut. */
obj1 = form->first;
while (obj1 != NULL)
{
i = -1;
while (obj1->shortcut[++i] != '\0')
if (obj1->shortcut[i] == key)
{
fl_handle_object(obj1,FL_SHORTCUT,xx,yy,key);
return;
}
obj1 = obj1->next;
}
if ( form->focusobj != NULL)
{
if ( (key == 9 || key == 13) && !form->focusobj->wantall)
{
obj = fl_find_object(form->focusobj->next,FL_FIND_INPUT,0.,0.);
if (obj == NULL) obj = fl_find_first(form,FL_FIND_INPUT,0.,0.);
fl_handle_object(form->focusobj,FL_UNFOCUS,xx,yy,0);
fl_handle_object(obj,FL_FOCUS,xx,yy,0);
}
else
fl_handle_object(form->focusobj,FL_KEYBOARD,xx,yy,key);
}
break;
case FL_STEP: /* A simple step */
obj1 = fl_find_first(form,FL_FIND_AUTOMATIC,0.0,0.0);
if (obj1 != NULL) fl_set_forms_window(form); /* set only if required */
while (obj1 != NULL)
{
fl_handle_object(obj1,FL_STEP,xx,yy,0);
obj1 = fl_find_object(obj1->next,FL_FIND_AUTOMATIC,0.0,0.0);
}
break;
}
}
/***************
Routine to check for events
***************/
static long lastsec = 0;
static long lastusec = 0;
static struct timeval tp;
static struct timezone tzp;
static void reset_time()
/* Resets the timer */
{
gettimeofday(&tp,&tzp);
lastsec = tp.tv_sec; lastusec = tp.tv_usec;
}
static float time_passed()
/* Returns the time passed since the last call */
{
gettimeofday(&tp,&tzp);
return (float) (tp.tv_sec - lastsec) + 0.000001 * (tp.tv_usec - lastusec);
}
static void do_interaction_step(int wait)
/* Checks the devices and takes action accordingly.*/
{
int i;
Device dev;
short val;
/* check devices */
if (!qtest())
{
if (time_passed()<0.01)
{ if (wait) sginap(1); else return;}
reset_time();
}
/* Ignore NULLDEV events (when used over network) */
do
if (!qtest()) dev = TIMER3; else dev = (Device) qread(&val);
while(dev == NULLDEV);
if (mouseform == NULL && dev != REDRAW && dev != INPUTCHANGE && dev != TIMER3
&& dev != WINFREEZE && dev != WINTHAW)
{ fl_qenter(dev,val); return; }
switch (dev)
{
case WINFREEZE:
for (i=0; i<formnumb; i++)
if (forms[i]->window == val)
{ fl_deactivate_form(forms[i]); return;}
fl_qenter(dev,val);
break;
case WINTHAW:
for (i=0; i<formnumb; i++)
if (forms[i]->window == val)
{ fl_activate_form(forms[i]); return;}
fl_qenter(dev,val);
break;
case REDRAW:
for (i=0; i<formnumb; i++)
if (forms[i]->window == val)
{fl_handle_form(forms[i],FL_DRAW,0);return;}
fl_qenter(dev,val);
break;
case MOUSE1:
case MOUSE2:
case MOUSE3:
if (val)
{
if (getbutton(PAUSEKEY))
fl_show_message("FORMS LIBRARY","version 2.2a", "Written by Mark Overmars");
else
fl_handle_form(mouseform,FL_PUSH,dev-MOUSE1+1);
}
else
fl_handle_form(mouseform,FL_RELEASE,dev-MOUSE1+1);
break;
case INPUTCHANGE:
/* leaving a window can cause val to be 256 (rather than 0) when
* used over the network.
*/
if ((val & 0xff) == 0)
{
if (mouseform == NULL)
fl_qenter(dev,val);
else
{ fl_handle_form(mouseform,FL_LEAVE,0); mouseform = NULL; }
}
else
{
if (mouseform != NULL)
{ fl_handle_form(mouseform,FL_LEAVE,0); mouseform = NULL; }
for (i=0; i<formnumb; i++)
if (forms[i]->window == val)
{ mouseform=forms[i]; fl_handle_form(mouseform,FL_ENTER,0); return;}
fl_qenter(dev,val);
}
break;
case LEFTARROWKEY:
if (val) fl_handle_form(mouseform,FL_KEYBOARD,1);
break;
case RIGHTARROWKEY:
if (val) fl_handle_form(mouseform,FL_KEYBOARD,2);
break;
case UPARROWKEY:
if (val) fl_handle_form(mouseform,FL_KEYBOARD,3);
break;
case DOWNARROWKEY:
if (val) fl_handle_form(mouseform,FL_KEYBOARD,4);
break;
case KEYBD:
fl_handle_form(mouseform,FL_KEYBOARD,val);
break;
case TIMER3:
fl_handle_form(mouseform,FL_MOUSE,0);
for (i=0; i<formnumb; i++) fl_handle_form(forms[i],FL_STEP,0);
break;
default:
fl_qenter(dev,val);
}
}
void fl_treat_interaction_events(int wait)
/* Handles all events in the input queue */
{
fl_save_user_window();
do do_interaction_step(wait); while (qtest());
fl_restore_user_window();
}
FL_OBJECT *fl_check_forms()
/* Checks all forms. Does not wait. */
{
FL_OBJECT *obj;
fl_save_user_window();
if ( (obj = fl_object_qread()) == NULL)
{
fl_treat_interaction_events(FALSE);
fl_treat_user_events();
obj = fl_object_qread();
}
fl_restore_user_window();
return obj;
}
FL_OBJECT *fl_do_forms()
/* Checks all forms. Waits if nothing happens. */
{
FL_OBJECT *obj;
fl_save_user_window();
while (1)
{
if ( (obj = fl_object_qread()) != NULL)
{ fl_restore_user_window(); return obj; }
fl_treat_interaction_events(TRUE);
fl_treat_user_events();
}
}
FL_OBJECT *fl_check_only_forms()
/* Same as fl_check_forms but never returns FL_EVENT. */
{
FL_OBJECT *obj;
fl_save_user_window();
if ( (obj = fl_object_qread()) == NULL)
{
fl_treat_interaction_events(FALSE);
obj = fl_object_qread();
}
fl_restore_user_window();
return obj;
}
FL_OBJECT *fl_do_only_forms()
/* Same as fl_do_forms but never returns FL_EVENT. */
{
FL_OBJECT *obj;
fl_save_user_window();
while (1)
{
if ( (obj = fl_object_qread()) != NULL)
{ fl_restore_user_window(); return obj; }
fl_treat_interaction_events(TRUE);
}
}